#include "asio_AsyncConnector.h"
#include "asio_NetworkHandler.h"
#include "asio_NetworkPacket.h"
#include "asio_header.h"
#include "ClientHandler.h"

namespace XGC
{
	namespace net
	{
		static thread* g_connect_thread = xgc_nullptr;

		void handle_connect( asio_SocketPtr pSocket, IMessageQueue* pMessageQueue, const system::error_code& error )
		{
			if (!error)
			{
				pSocket->accpet();
			}
			else
			{
				pSocket->close();
				if( pMessageQueue )
				{
					asio_NetworkPacket* pPacket = new asio_NetworkPacket( -1, NULL );
					if( pPacket )
					{
						static char msg[] = { SYSTEM_MESSAGE_TYPE, EVENT_ERROR };
						pPacket->putn( msg, sizeof(msg) );
						pMessageQueue->PushMessage( pPacket );
					}
				}
			}
		}

		void handle_stop()
		{
			asio_HandlerManager::Instance().CloseAll();
		}

		void StopConnector( io_service* service )
		{
			if( g_connect_thread )
			{
				service->post( handle_stop );

				g_connect_thread->join();

				SAFE_DELETE( g_connect_thread );
			}
		}

		bool AsyncConnect( io_service& service, const char* pszAddress, short port, IMessageQueue* pMessageQueue, _uint32 nTimerInvent )
		{
			system::error_code ec;
			ip::address_v4 addr( ip::address_v4::from_string( pszAddress, ec ) );
			if( ec )
				return false;

			asio_SocketPtr pSocket( new asio_Socket( service, new CClientHandler( pMessageQueue ), nTimerInvent ) );
			pSocket->socket().async_connect( 
				ip::tcp::endpoint( addr, port ), 
				boost::bind( handle_connect, pSocket, pMessageQueue, asio::placeholders::error )
				);

			if( !g_connect_thread )
			{
				g_connect_thread = new thread(boost::bind(&asio::io_service::run, &service));
			}
			return true;
		}

		bool DirectConnect( io_service& service, const char* pszAddress, short port, IMessageQueue* pMessageQueue, _uint32 nTimerInvent )
		{
			system::error_code ec;
			ip::address_v4 addr( ip::address_v4::from_string( pszAddress, ec ) );
			if( ec )
				return false;

			asio_SocketPtr pSocket( new asio_Socket( service, new CClientHandler( pMessageQueue ), nTimerInvent ) );

			if( pSocket->socket().connect( ip::tcp::endpoint( addr, port ), ec ) == 0 )
			{
				handle_connect( pSocket, pMessageQueue, ec );

				if( !g_connect_thread )
				{
					g_connect_thread = new thread(boost::bind(&asio::io_service::run, &service));
				}
			}

			return !ec;
		}
	}
}